package gd.blue.qaq.util.area;

import org.bukkit.configuration.serialization.*;
import org.bukkit.block.*;

import java.util.*;
import javax.annotation.*;

import org.bukkit.*;
import org.bukkit.entity.Player;

public class Area implements ConfigurationSerializable {
    private final Location minLocation;
    private final Location maxLocation;

    public void getAllBlocks() {
        for (final Location loc : this.get(this.minLocation, this.maxLocation)) {
            loc.getBlock().setType(Material.STONE);
        }
    }

    public void setTargetBlocksMaterial(final Material material) {
        for (final Location loc : this.get(this.minLocation, this.maxLocation)) {
            final Block block = loc.getBlock();
            if (block.getType().equals((Object) material)) {
                block.setType(Material.STONE);
            }
        }
    }

    public static Area locationsToArea(final Map<String, String> locations) {
        return new Area(new Location(Bukkit.getWorld((String) locations.get("world")), (double) Double.valueOf(locations.get("x1")), (double) Double.valueOf(locations.get("y1")), (double) Double.valueOf(locations.get("z1"))), new Location(Bukkit.getWorld((String) locations.get("world")), (double) Double.valueOf(locations.get("x2")), (double) Double.valueOf(locations.get("y2")), (double) Double.valueOf(locations.get("z2"))));
    }

    public List<Location> get(final Location min, final Location max) {
        final List<Location> locs = new ArrayList<Location>();
        for (int x = min.getBlockX(); x <= max.getBlockX(); ++x) {
            for (int y = min.getBlockY(); y <= max.getBlockY(); ++y) {
                for (int z = min.getBlockZ(); z <= max.getBlockZ(); ++z) {
                    locs.add(new Location(min.getWorld(), (double) x, (double) y, (double) z));
                }
            }
        }
        return locs;
    }

    public Area(@Nonnull final Location point1, @Nonnull final Location point2) {
        if (!point1.getWorld().equals(point2.getWorld())) {
            throw new IllegalArgumentException("Area cannot be created between different worlds");
        }
        double x1 = point1.getX();
        double x2 = point2.getX();
        double y1 = point1.getY();
        double y2 = point2.getY();
        double z1 = point1.getZ();
        double z2 = point2.getZ();
        if (x1 > x2) {
            final double t = x1;
            x1 = x2;
            x2 = t;
        }
        if (y1 > y2) {
            final double t = y1;
            y1 = y2;
            y2 = t;
        }
        if (z1 > z2) {
            final double t = z1;
            z1 = z2;
            z2 = t;
        }
        this.minLocation = new Location(point1.getWorld(), x1, y1, z1);
        this.maxLocation = new Location(point2.getWorld(), x2, y2, z2);
    }

    public final World getWorld() {
        return this.minLocation.getWorld();
    }

    public final Location getMinLocation() {
        return this.minLocation;
    }

    public final Location getMaxLocation() {
        return this.maxLocation;
    }

    public boolean contain(final Location location) {
        return location != null && this.getMinLocation().getWorld().equals(location.getWorld()) && this.getMinLocation().getX() <= location.getX() && this.getMinLocation().getY() <= location.getY() && this.getMinLocation().getZ() <= location.getZ() && this.getMaxLocation().getX() >= location.getX() && this.getMaxLocation().getY() >= location.getY() && this.getMaxLocation().getZ() >= location.getZ();
    }

    public boolean contain(final Area area) {
        return area != null && this.getMinLocation().getWorld().equals(area.getMinLocation().getWorld()) && this.getMinLocation().getX() <= area.getMinLocation().getX() && this.getMinLocation().getY() <= area.getMinLocation().getY() && this.getMinLocation().getZ() <= area.getMinLocation().getZ() && this.getMaxLocation().getX() >= area.getMaxLocation().getX() && this.getMaxLocation().getY() >= area.getMaxLocation().getY() && this.getMaxLocation().getZ() >= area.getMaxLocation().getZ();
    }

    public boolean intersect(final Area area) {
        return area != null && (this.contain(area.getMinLocation()) || this.contain(area.getMaxLocation()) || area.contain(this.getMinLocation()) || area.contain(this.getMaxLocation()));
    }

    @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Area)) {
            return false;
        }
        final Area other = (Area) obj;
        return this.getMinLocation().equals((Object) other.getMinLocation()) && this.getMaxLocation().equals((Object) other.getMaxLocation());
    }

    @Override
    public int hashCode() {
        return this.getMinLocation().hashCode() * 37 + this.getMaxLocation().hashCode();
    }

    @Override
    public String toString() {
        return "Area: {MaxLocation: " + this.getMinLocation().toString() + ", MinLocation: " + this.getMaxLocation().toString() + " }";
    }

    public Map<String, Object> serialize() {
        return null;
    }
}
